﻿
namespace QFramework
{
    using FairyGUI;
    using System.Collections.Generic;
    using System.Text;
    using System.IO;
    using UnityEditor;

    public class FGUICodeGenerator
    {
        public class FguiInfo
        {
            public FguiType currentType;
            public string infoName;
        }

        public enum FguiType
        {
            Controllers,
            Children,
            Source_sound,
            Source_MovieClip,
            Source_Atlas,
            Source_Font,
            Source_Image,
            Source_Misc,
        }

        static List<string> m_ChildrenList = new List<string>();
        static List<string> m_ControllList = new List<string>();
        static List<FguiInfo> m_SourceList = new List<FguiInfo>();

        public static void AddInfo(FguiType selfType, string info)
        {
            switch (selfType)
            {
                case FguiType.Children:
                    if (m_ChildrenList == null)
                        m_ChildrenList = new List<string>();
                    m_ChildrenList.Add(info);
                    break;
                case FguiType.Controllers:
                    if (m_ControllList == null)
                        m_ControllList = new List<string>();
                    m_ControllList.Add(info);
                    break;
                default:
                    if (m_SourceList == null)
                        m_SourceList = new List<FguiInfo>();

                    m_SourceList.Add(new FguiInfo() { currentType = selfType, infoName = info });
                    break;
            }
        }

        public static void CreateCode()
        {
            string Scriptname = _packName + "_" + _scriptName;
            string Legalname = GetLegalname(Scriptname);

            CreateBehaviourCode(Legalname);
            CreateComponentCode(Legalname);

            AssetDatabase.Refresh();
        }

        private static string GetLegalname(string text)
        {
            return text.Replace('$', '_').Replace('&', '_').Replace('*', '_').Replace('^', '_').Replace('.','_').Replace(" ","").Replace("(","").Replace(")","");
        }

        public static void CreateResCode()
        {
            string Scriptname = _packName + "_Source";
            string Legalname = GetLegalname(Scriptname);

            CreateSourceCode(Legalname);

            AssetDatabase.Refresh();
        }

        private static void CreateBehaviourCode(string scriptName)
        {
            string ScriptPath = string.Format("{0}/{1}.cs", FGUIScriptPathDefine.FGUIScriptPath, scriptName);

            if (File.Exists(ScriptPath))
            {
                return;
            }

            StringBuilder stringBuilder = new StringBuilder();
            StreamWriter streamWriter = new StreamWriter(ScriptPath, false, Encoding.UTF8);

            stringBuilder.AppendLine("namespace QFramework");
            stringBuilder.AppendLine("{");
            stringBuilder.Append("\t").AppendLine("using UnityEngine;");
            stringBuilder.Append("\t").AppendLine("using FairyGUI;").AppendLine();

            stringBuilder.Append("\t").AppendFormat("public class {0} : IUIData", scriptName + "Data").AppendLine();
            stringBuilder.Append("\t").AppendLine("{").AppendLine();
            stringBuilder.Append("\t").AppendLine("}").AppendLine();

            stringBuilder.Append("\t").AppendFormat("public partial class {0} : FGUIBehaviour", scriptName).AppendLine();
            stringBuilder.Append("\t").AppendLine("{");
            stringBuilder.Append("\t\t").AppendLine("protected override void InitUI(IUIData uiData = null)");
            stringBuilder.Append("\t\t").AppendLine("{");
            stringBuilder.Append("\t\t\t").AppendFormat("m_Data = uiData as {0};", scriptName + "Data").AppendLine();
            stringBuilder.Append("\t\t").AppendLine("}");

            stringBuilder.AppendLine();
            stringBuilder.Append("\t\t").AppendLine("protected override void ProcessMsg(int eventId, QMsg msg)");
            stringBuilder.Append("\t\t").AppendLine("{").AppendLine();
            stringBuilder.Append("\t\t").AppendLine("}").AppendLine();

            stringBuilder.Append("\t\t").AppendLine("protected override void RegisterUIEvent()");
            stringBuilder.Append("\t\t").AppendLine("{").AppendLine();
            stringBuilder.Append("\t\t").AppendLine("}").AppendLine();

            stringBuilder.Append("\t\t").AppendLine("protected override void Button(string ButtonName)");
            stringBuilder.Append("\t\t").AppendLine("{").AppendLine();
            stringBuilder.Append("\t\t").AppendLine("}").AppendLine();

            stringBuilder.Append("\t\t").AppendLine("protected override void OnShow()");
            stringBuilder.Append("\t\t").AppendLine("{");
            stringBuilder.Append("\t\t\t").AppendLine("base.OnShow();");
            stringBuilder.Append("\t\t").AppendLine("}").AppendLine();

            stringBuilder.Append("\t\t").AppendLine("protected override void OnHide()");
            stringBuilder.Append("\t\t").AppendLine("{");
            stringBuilder.Append("\t\t\t").AppendLine("base.OnHide();");
            stringBuilder.Append("\t\t").AppendLine("}").AppendLine();

            stringBuilder.Append("\t\t").AppendLine("protected override void OnBeforeDestroy()");
            stringBuilder.Append("\t\t").AppendLine("{");
            stringBuilder.Append("\t\t\t").AppendLine("base.OnBeforeDestroy();");
            stringBuilder.Append("\t\t").AppendLine("}").AppendLine();

            stringBuilder.Append("\t\t").AppendLine("void ShowLog(string content)");
            stringBuilder.Append("\t\t").AppendLine("{");
            stringBuilder.Append("\t\t\t").AppendFormat("Debug.Log(\"[{0}:]\" + content);", scriptName).AppendLine();
            stringBuilder.Append("\t\t").AppendLine("}").AppendLine();

            stringBuilder.Append("\t\t").AppendFormat("{0} m_Data = null;", scriptName + "Data").AppendLine();
            stringBuilder.Append("\t").AppendLine("}");
            stringBuilder.Append("}");

            streamWriter.Write(stringBuilder);
            streamWriter.Flush();
            streamWriter.Close();
        }

        private static void CreateSourceCode(string scriptName)
        {
            string ScriptPath = string.Format("{0}/{1}.cs", FGUIScriptPathDefine.FGUIPackPath, scriptName);

            StringBuilder stringBuilder = new StringBuilder();
            StreamWriter streamWriter = new StreamWriter(ScriptPath, false, Encoding.UTF8);

            stringBuilder.AppendLine("namespace QFramework");
            stringBuilder.AppendLine("{");

            stringBuilder.Append("\t").AppendFormat("public class {0}", scriptName).AppendLine();
            stringBuilder.Append("\t").AppendLine("{");

            for (int i = 0; i < m_SourceList.Count; i++)
            {
                if (m_SourceList[i].infoName != null)
                {
                    string infoname = GetLegalname(m_SourceList[i].infoName);
                    stringBuilder.Append("\t\t\t").AppendFormat("public static string {0} = \"{1}\";", m_SourceList[i].currentType.ToString() + "_" + infoname, m_SourceList[i].infoName).AppendLine();
                }
            }

            stringBuilder.Append("\t").AppendLine("}");
            stringBuilder.AppendLine("}");

            streamWriter.Write(stringBuilder);
            streamWriter.Flush();
            streamWriter.Close();

        }

        private static void CreateComponentCode(string scriptName)
        {
            string ScriptPath = string.Format("{0}/{1}.cs", FGUIScriptPathDefine.FGUIComponentPath, scriptName + "Component");

            StringBuilder stringBuilder = new StringBuilder();
            StreamWriter streamWriter = new StreamWriter(ScriptPath, false, Encoding.UTF8);

            stringBuilder.AppendLine("namespace QFramework");
            stringBuilder.AppendLine("{");
            stringBuilder.Append("\t").AppendLine("using FairyGUI;");
            stringBuilder.Append("\t").AppendFormat("public partial class {0}", scriptName).AppendLine();
            stringBuilder.Append("\t").AppendLine("{");

            stringBuilder.AppendLine("//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

            foreach (var controller in m_ControllList)
            {              
                stringBuilder.Append("\t\t").AppendFormat("private Controller controller_{0} {{ get {{ return m_Compoent.GetController(\"{0}\");}}}}", controller).AppendLine();              
            }

            stringBuilder.AppendLine("//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

            foreach (var component in m_ChildrenList)
            {
                string legalname = GetLegalname(component);

                stringBuilder.Append("\t\t").AppendFormat("private GObject data_{0};", legalname).AppendLine();
                stringBuilder.Append("\t\t").AppendFormat("private GObject {0}", legalname).AppendLine();
                stringBuilder.Append("\t\t").AppendLine("{");
                stringBuilder.Append("\t\t\t").AppendLine("get");
                stringBuilder.Append("\t\t\t").AppendLine("{");
                stringBuilder.Append("\t\t\t\t").AppendFormat("if (data_{0} == null)", legalname).AppendLine();
                stringBuilder.Append("\t\t\t\t").AppendLine("{");
                stringBuilder.Append("\t\t\t\t\t").AppendFormat("data_{0} = m_Compoent.GetChild(\"{1}\");",legalname ,component).AppendLine();
                stringBuilder.Append("\t\t\t\t").AppendLine("}");
                stringBuilder.Append("\t\t\t\t").AppendFormat("return data_{0};", legalname).AppendLine();
                stringBuilder.Append("\t\t\t").AppendLine("}");
                stringBuilder.Append("\t\t").AppendLine("}").AppendLine();
            }

            stringBuilder.AppendLine("//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

            stringBuilder.Append("\t").AppendLine("}");
            stringBuilder.AppendLine("}");

            streamWriter.Write(stringBuilder);
            streamWriter.Flush();
            streamWriter.Close();
        }

        public static void BeginCom(string packName,string ScriptName)
        {
            m_ControllList.Clear();
            m_ChildrenList.Clear();
            _packName = packName;
            _scriptName = ScriptName;
        }

        public static void BeginSource()
        {
            m_SourceList.Clear();
        }

        private static string _packName;
        private static string _scriptName;
    }
}
